package com.youlian.cloud.core.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.commons.beanutils.BeanUtils;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * @author liuhx on 2016/12/11 22:27
 * @version V1.0
 * @email liuhx@elab-plus.com
 */
public class ObjectUtils extends org.apache.commons.lang3.ObjectUtils{

    private static Pattern pattern = Pattern.compile("^[-+]?(([0-9]+)([.]([0-9]+))?|([.]([0-9]+))?)$");

    public ObjectUtils() {
    }

    public static boolean isEmpty(Object obj) {
        return obj == null || !StringUtils.isNotEmpty(obj.toString());
    }

    public static Object objIsNull(Object obj) {
        return obj != null && !"null".toUpperCase().equals(obj.toString().toUpperCase()) ? obj : null;
    }

    public static String parseJsonNode(JSONObject value) {
        if (value == null) {
            return null;
        } else {
            String str = value.toJSONString();
            return StringUtils.isNotEmpty(str) && !"null".equals(str) ? str : null;
        }
    }

    public static Double objIsNullByZero(Object obj) {
        if (obj != null && StringUtils.isNotEmpty(obj.toString())) {
            Double value = parseDouble(obj);
            return Double.valueOf(value == null ? 0.0D : value.doubleValue());
        } else {
            return Double.valueOf(BigDecimal.valueOf(0.0D).setScale(2, 1).doubleValue());
        }
    }

    public static Double objIsNullByZero(JSON obj) {
        if (obj != null && StringUtils.isNotEmpty(obj.toJSONString())) {
            Double value = parseDouble((Object) obj.toJSONString());
            return Double.valueOf(value == null ? 0.0D : value.doubleValue());
        } else {
            return Double.valueOf(BigDecimal.valueOf(0.0D).setScale(2, 1).doubleValue());
        }
    }

    public static boolean isNotEmpty(Object obj) {
        return obj != null && StringUtils.isNotEmpty(obj.toString());
    }

    public static boolean isNumber(Object value) {
        if (value != null && StringUtils.isNotEmpty(value.toString())) {

            return pattern.matcher(value.toString()).matches();
        } else {
            return false;
        }
    }

    public static Double parseDouble(Object obj) {
        if (obj != null && isNumber(obj)) {
            BigDecimal bd = BigDecimal.valueOf(Double.parseDouble(obj.toString())).setScale(2, 1);
            return Double.valueOf(bd.doubleValue());
        } else {
            return null;
        }
    }

    public static Double parseDouble(JSON obj) {
        if (obj != null && StringUtils.isNotEmpty(obj.toJSONString())) {
            String text = obj.toJSONString();
            return parseDouble((Object) text);
        } else {
            return null;
        }
    }

    public static Double addition(Object obj1, Object obj2) {
        if (isNumber(obj1) && isNumber(obj2)) {
            BigDecimal bd = BigDecimal.valueOf(Double.parseDouble(obj1.toString())).add(BigDecimal.valueOf(Double.parseDouble(obj2.toString())));
            return Double.valueOf(bd.setScale(2, 1).doubleValue());
        } else {
            return null;
        }
    }

    public static Double subtract(Object obj1, Object obj2) {
        if (isNumber(obj1) && isNumber(obj2)) {
            BigDecimal bd = BigDecimal.valueOf(Double.parseDouble(obj1.toString())).subtract(BigDecimal.valueOf(Double.parseDouble(obj2.toString())));
            return Double.valueOf(bd.setScale(2, 1).doubleValue());
        } else {
            return null;
        }
    }

    public static String parseDateTime(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String dateStr = sdf.format(sdf);
        return dateStr;
    }

    /**
     * 将一个date类型的数据转化成字符串
     *
     * @param date
     * @return
     */
    public static String parseDate(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String dateStr = sdf.format(sdf);
        return dateStr;
    }

    /**
     * 判断集合是否为空
     *
     * @param list
     * @return
     */
    public static boolean listIsNull(List list) {
        return list == null || list.size() <= 0;
    }


    public static String jsonNodeParseStr(JSON jsonNode) {
        return jsonNode == null ? null : jsonNode.toString();
    }

    public static String objectParseJsonStr(Object object) {
        return object == null ? null : JSON.toJSONString(object);
    }

    public static JSONObject strParseJsonNode(String jsonStr) {
        if (StringUtils.isNotEmpty(jsonStr)) {
            return JSONObject.parseObject(jsonStr);
        }

        return null;
    }

    /**
     * 空字符串替换成null
     *
     * @param str
     * @return
     */
    public static String strParseNull(String str) {
        if (StringUtils.isNotEmpty(str)) {
            return str;
        }
        return null;
    }

    public static ObjectNode newJsonNode() {
        return (new ObjectMapper()).createObjectNode();
    }

    public static String parseJsonNodeNullStr(JsonNode value) {
        if (value == null) {
            return "";
        } else {
            String v = value.asText();
            return isNotEmpty(v) && !"null".equals(v) ? v : "";
        }
    }

    /**
     * 修改集合中的属性值
     * %s 表示原来属性位置的老的值
     *
     * @param list              需要更改的集合对象
     * @param updatePropertyMap 修改属性的描述Map -> %s 表示老的值 [例如: 原来属性的值bbb,需要修改这个值,key的value为 aaa%s 结果就会 aaabbb
     * @return
     */
    public static void updateBeanProperty(List list, Map<String, String> updatePropertyMap) {
        updateBeanProperty(list, updatePropertyMap, false);
    }

    /**
     * 修改集合中的属性值
     * %s 表示原来属性位置的老的值
     *
     * @param list              需要更改的集合对象
     * @param updatePropertyMap 修改属性的描述Map -> %s 表示老的值 [例如: 原来属性的值bbb,需要修改这个值,key的value为 aaa%s 结果就会 aaabbb
     * @param isNull            为null的属性是否也需要修改,true 修改 , false 不修改
     */
    public static void updateBeanProperty(List list, Map<String, String> updatePropertyMap, boolean isNull) {
        if (list == null || list.size() == 0) {
            return;
        }

        for (int i = 0; i < list.size(); i++) {
            Object t = list.get(i);
            // 遍历map集合
            for (Map.Entry<String, String> entry : updatePropertyMap.entrySet()) {
                try {
                    String key = entry.getKey();
                    String value = entry.getValue();
                    String property = BeanUtils.getProperty(t, key);
                    if (isEmpty(value) || (!isNull && isEmpty(property))) {
                        continue;
                    }
                    BeanUtils.setProperty(t, key, String.format(value, property));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 修改集合中的对象属性值
     *
     * @param list  需要修改的对象集合
     * @param key   修改的属性名称
     * @param value 修改成的值 , %s 表示老的值
     */
    public static void updateBeanProperty(List list, String key, String value) {
        if (list == null || list.size() == 0) {
            return;
        }

        for (int i = 0; i < list.size(); i++) {
            Object t = list.get(i);
            // 遍历map集合
            try {
                String property = BeanUtils.getProperty(t, key);
                if (isEmpty(value) || isEmpty(property)) {
                    continue;
                }
                BeanUtils.setProperty(t, key, String.format(value, property));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 将集合属性的值赋给另外一个对象,并且生成一个集合
     *
     * @param list        原始集合
     * @param propertyMap 参数对应的Map,如果两个对象的属性名称一致,则可以不用传递,这里只要传入差异化的属性对应
     * @param clazz       转换成的对象
     * @param <T>
     * @return
     */
    public static <T> List<T> copyListPropertyValue(List list, Map<String, String> propertyMap, Class<T> clazz) {
        if (list == null || list.size() == 0) {
            return null;
        }
        List resultList = new ArrayList();
        for (int i = 0; i < list.size(); i++) {
            try {
                Object sourceObject = list.get(i);
                Object newSourceObject = clazz.newInstance();
                BeanUtils.copyProperties(newSourceObject, sourceObject);
                // 遍历map集合
                for (Map.Entry<String, String> entry : propertyMap.entrySet()) {
                    String key = entry.getKey();
                    String value = entry.getValue();
                    String property = BeanUtils.getProperty(sourceObject, key);
                    if (isNotEmpty(property)) {
                        BeanUtils.setProperty(newSourceObject, value, property);
                    }
                }
                resultList.add(newSourceObject);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return resultList;
    }


}
